package com.gukun.springboot.tdengine.service.backuprecover;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gukun.springboot.tdengine.dao.BackupRecoverTaskMapper;
import com.gukun.springboot.tdengine.domain.backuprecover.BackupRecoverLogEntity;
import com.gukun.springboot.tdengine.domain.backuprecover.BackupRecoverTaskEntity;
import com.gukun.springboot.tdengine.domain.exception.util.ServiceExceptionUtil;
import com.gukun.springboot.tdengine.service.backuprecover.backup.BackupExecutor;
import com.gukun.springboot.tdengine.service.backuprecover.recover.RecoverExecutor;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zhang
 */
@Service
@Slf4j
public class BackupRecoverTaskService{
    @Autowired
    private BackupRecoverTaskMapper backupRecoverTaskMapper;
    @Autowired
    private BackupRecoverLogService backupRecoverLogService;
    @Autowired
    private BackupExecutor backupExecutor;
    @Autowired
    private RecoverExecutor recoverExecutor;

    public boolean saveOrUpdateBackupTask(BackupRecoverTaskEntity backupTask) {
        String name = backupTask.getName();
        String id = backupTask.getId();
        LambdaQueryWrapper<BackupRecoverTaskEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(BackupRecoverTaskEntity::getName, name);
        if(StringUtils.isNotBlank(id)){
            queryWrapper.ne(BackupRecoverTaskEntity::getId, id);
        }
        long num = backupRecoverTaskMapper.selectCount(queryWrapper);
        if(num > 0){
            throw ServiceExceptionUtil.exception0(200, "任务名称重复！");
        }
        if (StringUtils.isBlank(id)) {
            backupTask.setCreateTime(DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
            return backupRecoverTaskMapper.insert(backupTask) == 1;
        } else {
            return backupRecoverTaskMapper.updateById(backupTask) == 1;
        }
    }

    public Page<BackupRecoverTaskEntity> getBackupAndRecoverTask(BackupRecoverTaskEntity backupRecoverTaskEntity) throws Exception {
        String hostAndPort = backupRecoverTaskEntity.getHostAndPort();
        LambdaQueryWrapper<BackupRecoverTaskEntity> queryWrapper = Wrappers.lambdaQuery();
        if(StringUtils.isNotBlank(hostAndPort)){
            queryWrapper.eq(BackupRecoverTaskEntity::getHostAndPort, hostAndPort);
        }
        String name = backupRecoverTaskEntity.getName();
        if(StringUtils.isNotBlank(name)){
            queryWrapper.like(BackupRecoverTaskEntity::getName, name);
        }
        String desc = backupRecoverTaskEntity.getDesc();
        if(StringUtils.isNotBlank(desc)){
            queryWrapper.like(BackupRecoverTaskEntity::getDesc, desc);
        }
        int operateType = backupRecoverTaskEntity.getOperateType();
        if(operateType != -1){
            queryWrapper.eq(BackupRecoverTaskEntity::getOperateType, operateType);
        }
        int status = backupRecoverTaskEntity.getStatus();
        if(status != -1){
            queryWrapper.eq(BackupRecoverTaskEntity::getStatus, status);
        }
        queryWrapper.orderByDesc(BackupRecoverTaskEntity::getCreateTime);
        Page<BackupRecoverTaskEntity> page = new Page<>();
        page.setCurrent(backupRecoverTaskEntity.getCurrent());
        page.setSize(backupRecoverTaskEntity.getSize());
        return backupRecoverTaskMapper.selectPage(page, queryWrapper);
    }

    public Boolean startTask(BackupRecoverTaskEntity backupRecoverTaskEntity) throws Exception {
        //增加限制，同时只能启动一个任务
        LambdaQueryWrapper<BackupRecoverTaskEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(BackupRecoverTaskEntity::getStatus,"1");
        if(backupRecoverTaskMapper.selectCount(queryWrapper) > 0){
            throw ServiceExceptionUtil.exception0(200, "有任务正在运行！");
        }
        int operateType = backupRecoverTaskEntity.getOperateType();
        if(operateType == 1){
            backupExecutor.execute(backupRecoverTaskEntity);
        }else if(operateType == 2){
            recoverExecutor.execute(backupRecoverTaskEntity);
        }
        return true;
    }

    public Boolean deleteTask(String id) {
        int result = backupRecoverTaskMapper.deleteById(id);
        if(result == 1){
            backupRecoverLogService.deleteLogByTaskId(id);
        }
        return result == 1;
    }

    public Boolean stopTask(String id) throws Exception{
        BackupRecoverTaskEntity backupRecoverTaskEntity = this.backupRecoverTaskMapper.selectById(id);
        int operateType = backupRecoverTaskEntity.getOperateType();
        if(backupRecoverTaskEntity.getStatus() == 0){
            throw ServiceExceptionUtil.exception0(200, "任务已停止！");
        }
        if(operateType == 1){
            backupExecutor.stopTask(id);
        }else if(operateType == 2){
            recoverExecutor.stopTask(id);
        }
        backupRecoverTaskEntity.setStatus(0);
        backupRecoverTaskMapper.updateById(backupRecoverTaskEntity);
        return true;
    }

    public void updateTaskStatusStop(BackupRecoverTaskEntity backupRecoverTaskEntity){
        backupRecoverTaskEntity.setStatus(0);
        backupRecoverTaskMapper.updateById(backupRecoverTaskEntity);
    }

    public void updateTaskStatusStart(BackupRecoverTaskEntity backupRecoverTaskEntity){
        backupRecoverTaskEntity.setStatus(1);
        backupRecoverTaskMapper.updateById(backupRecoverTaskEntity);
    }


    public void downloadTagInfo(String id, HttpServletResponse response) throws Exception {
        BackupRecoverLogEntity backupsLog = backupRecoverLogService.getById(id);
        BackupRecoverTaskEntity backupsTask = backupRecoverTaskMapper.selectById(backupsLog.getTaskId());
        String fileName = backupsLog.getFilePath();
        String zipPath =  System.getProperty("user.dir") + "/";
        zipPath = zipPath + backupsTask.getDbName() + ".zip";
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + backupsTask.getDbName() + "\"");
        ZipUtil.zip(fileName,zipPath);
        FileCopyUtils.copy(new FileSystemResource(new File(zipPath)).getInputStream(), response.getOutputStream());
        response.flushBuffer();
        FileUtil.del(zipPath);
    }

    public BackupRecoverTaskEntity getById(String id){
        return backupRecoverTaskMapper.selectById(id);
    }
}
